
#include "hal.h"
#include <hal_config.h>

#define IAP_CMD_READ_UID					0x04
#define IAP_CMD_APROM_PROGRAM_BYTE			0x21
#define IAP_CMD_APROM_ERASE_PAGE			0x22
#define IAP_CMD_CONFIGOM_PROGRAM			0xE1

bit BIT_TMP;

static uint8_t _IAP_CMD(uint16_t _IAPA, uint8_t _IAPCN, uint8_t _IAPFD)
{
	uint8_t ret;
	IAPAL = (uint8_t)_IAPA;
	IAPAH = (uint8_t)(_IAPA>>8);
	IAPFD = _IAPFD;
	IAPCN = _IAPCN;
	set_IAPEN;					//enable IAPEN
	set_IAPGO;					//Trig set IAPGO
	clr_IAPEN					//disable IAPEN
	ret = IAPFD;
	return ret;
}

#if (SW_DELAY_ENABLE == 1)
void delay_20us(volatile uint8_t nCount)	//20us
{
	volatile uint8_t i;
	for(; nCount != 0; nCount--){
		for(i = 0; i < 11; i++);
	}
}

void delay_1ms(volatile uint8_t nCount)
{
	volatile uint8_t i;
	for(; nCount != 0; nCount--){
		for(i = 0; i < 250; i++);
		for(i = 0; i < 250; i++);
		for(i = 0; i < 115; i++);
	}
}
#endif
#if (UART0_USE_TIMER1_ENABLE == 1)
void uart0_use_timer1_init(uint32_t u32Baudrate)    //T1M = 1, SMOD = 1
{
	P06_Quasi_Mode;		//Setting UART pin as Quasi mode for transmit
	P07_Quasi_Mode;		//Setting UART pin as Quasi mode for transmit
	
    SCON = 0x50;     	//UART0 Mode1,REN=1,TI=1
    TMOD |= 0x20;    	//Timer1 Mode1
    
    set_SMOD;        	//UART0 Double Rate Enable
    set_T1M;
    clr_BRCK;        	//Serial port 0 baud rate clock source = Timer1
 
#ifdef FOSC_160000
    TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */
#endif    	
#ifdef FOSC_166000
    TH1 = 256 - (1037500/u32Baudrate);         		     /*16.6 MHz */
#endif
    set_TR1;		//TM1 start
}

void uart0_send_data_blocked(uint8_t d)
{
    TI = 0;
    SBUF = d;
    while(TI==0);
}
#endif
#if (WKT_ENABLE == 1)
void wakeup_timer_init_with_calibration(uint8_t time_in_ms)
{
	unsigned long int temp;
	uint16_t tr0_c = 0;
	
	EA = 0;
	clr_WKTR;				//stop wkt
	clr_EWKT;												// enable WKT interrupt
	clr_WKTF;
//	clr_WKPS2; clr_WKPS1; set_WKPS0;	//dev = 4
// RWK 1 = 0.4ms --> RWK = next_interrupt_time_in_ms/0.4
//	RWK = 256 - 200;			//200*0.4 = 80ms
	
	clr_WKPS2; clr_WKPS1; clr_WKPS0;	//dev = 1
// RWK 1 = 0.1ms --> RWK = next_interrupt_time_in_ms/0.1
	RWK = 256 - 250;			//250*0.1 = 25ms
	
	clr_TR0;				//stop t0
	clr_ET0;
	TIMER0_MODE1_ENABLE;	//16bit
    clr_T0M;	//clock source Fsys/12 -> 16Mhz/12 -> 4/3Mhz	1tick = 3/4us
	//overflow tick = 0XFFFF+1 = 65536
	//overflow time = 65536*(3/4us) = 49.125 > 49ms
    TH0 = 0;
	TL0 = 0;
	
	set_WKTR; 												// Wake-up timer run
	set_TR0;				
	
	while(1){
		if(get_bit(WKCON, 4)){			//GET WLTF
			clr_TR0;
			clr_WKTR;
			
			tr0_c = TH0;
			tr0_c <<= 8;
			tr0_c += TL0;
/***********************************************************
 *     200(real_tick)           real_time        t0_ticks
 * -----------------------  =  -----------  =  -----------  
 *  WKT_calibration_ticks         80ms          80000/(3/4)
***********************************************************/
//			tr0_c = ((200*80000*4)/3)*/tr0_c;
			//tr0_c -> 80ms WKT_calibration_ticks;
			//1ms WKT_calibration_ticks = tr0_c/80
			
/***********************************************************
 *     250(real_tick)           real_time        t0_ticks
 * -----------------------  =  -----------  =  -----------  
 *  WKT_calibration_ticks         25ms          25000/(3/4)
***********************************************************/
//			tr0_c = ((250*25000*4)/3)*/tr0_c;
			temp = (250UL*25000UL*4UL)/3UL;
			temp = temp/tr0_c;
			break;
		}
	}
	
	temp = (time_in_ms*temp)/25;
	RWK  = 256 - (uint8_t)temp;
}

/********************************************************************************
f        dev     f/dev             bit           1/(f/dev)       (1/(f/dev))*(2^bit)
                                                 dev/f           (dev*(2^bit))/f
-------------------------------------------------------------------------------
10k      1       10k                8            0.1ms            25.6
10k      4       ...                8            0.4ms            102.4
10k      16      ...                8            1.6ms            409.6
10k      64      ...                8            6.4ms            1638.4
10k      256     ...                8            25.6ms           6553.6
10k      512     ...                8            51.2ms           13107.2
10k      1024    ...                8            102.4ms          26214.4
10k      2048    ...                8            204.8ms          52428.8
********************************************************************************/
uint16_t wakeup_timer_set_next_interrupt_time(uint16_t next_interrupt_time_in_ms)
{
	unsigned long int temp;

	if(next_interrupt_time_in_ms > 52428){
		next_interrupt_time_in_ms = 52428;
	}

	temp = next_interrupt_time_in_ms;
	if(next_interrupt_time_in_ms <= 102){				//1~102
		clr_WKPS2; clr_WKPS1; set_WKPS0;	//dev = 4
		// RWK 1 = 0.4ms --> RWK = next_interrupt_time_in_ms/0.4
		temp = ((temp*10)>>2);
		RWK = 256 - (uint8_t)temp;
		next_interrupt_time_in_ms = (uint8_t)temp+1;
		next_interrupt_time_in_ms = (next_interrupt_time_in_ms<<2)/10;
	}
	else if(next_interrupt_time_in_ms <= 26214){		//103~26214
		set_WKPS2; set_WKPS1; clr_WKPS0;	//dev = 1024
		// RWK 1 = 102.4ms --> RWK = next_interrupt_time_in_ms/102.4
		temp = (temp*10)>>10;
		RWK = 256 - (uint8_t)temp;
		next_interrupt_time_in_ms = (uint8_t)temp;
		next_interrupt_time_in_ms = (next_interrupt_time_in_ms<<10)/10;
	}
	else{												//26214~52428
		set_WKPS2; set_WKPS1; set_WKPS0;	//dev = 2048
		// RWK 1 = 204.8ms --> RWK = next_interrupt_time_in_ms/204.8
		temp = (temp*10)>>11;
		RWK = 256 - (uint8_t)temp;
		next_interrupt_time_in_ms = (uint8_t)temp;
		next_interrupt_time_in_ms = (next_interrupt_time_in_ms<<11)/10;
	}

	set_EWKT;												// enable WKT interrupt
//	set_WKTR; 												// Wake-up timer run
	if(next_interrupt_time_in_ms != 0){
		return next_interrupt_time_in_ms;
	}
	else{
		return 1;
	}
}
#endif
#if (WDT_ENABLE == 1)
/***********************************************************************
	WDT CONFIG enable 
	warning : this macro is only when ICP not enable CONFIG WDT function
	copy this marco code to you code to enable WDT reset.
************************************************************************/
//void Enable_WDT_Reset_Config(void)
//{
//	  set_IAPEN;
//   IAPAL = 0x04;
//   IAPAH = 0x00;
//   IAPFD = 0x0F;
//   IAPCN = 0xE1;
//   set_CFUEN;
//   set_IAPGO;                                  //trigger IAP
//		while((CHPCON&SET_BIT6)==SET_BIT6);          //check IAPFF (CHPCON.6)
//   clr_CFUEN;
//   clr_IAPEN;

//    set_CFUEN;
//	_IAP_CMD(0x0004, IAP_CMD_CONFIGOM_PROGRAM, 0xF0);
//	clr_CFUEN;
//}

void wdt_init(void)
{
	set_IAPEN;
	IAPAL = 0x04;
	IAPAH = 0x00;
	IAPFD = 0x0F;
	IAPCN = 0xE1;
	set_CFUEN;
	set_IAPGO;                                  //trigger IAP
	while((CHPCON&SET_BIT6)==SET_BIT6);          //check IAPFF (CHPCON.6)
	clr_CFUEN;
	clr_IAPEN;
	
	TA=0xAA;TA=0x55;
	WDCON=0x07;						//Setting WDT prescale 1.638Ss
	set_WDCLR;						//Clear WDT timer
	while((WDCON|~SET_BIT6)==0xFF);				//confirm WDT clear is ok before into power down mode
	set_WDTR;	
}
#endif
#if (GPIO_ENABLE == 1)
/******************
M1 	0	0	1	1
M2 	0	1	0	1
	BD	PP	HI	OD
******************/
void gpio_mode_config(uint8_t port, uint8_t pin, uint8_t mode)
{
	switch(port){
		case 0:
			switch(mode){
				case GPIO_MODE_BD:
					reset_bit(P0M1, pin);
					reset_bit(P0M2, pin);
					break;
				case GPIO_MODE_PP:
					reset_bit(P0M1, pin);
					set_bit(P0M2, pin);
					break;
				case GPIO_MODE_HI:
					set_bit(P0M1, pin);
					reset_bit(P0M2, pin);
					break;
				case GPIO_MODE_OD:
					set_bit(P0M1, pin);
					set_bit(P0M2, pin);
					break;
				default:
					break;
			}
			break;

		case 1:
			switch(mode){
				case GPIO_MODE_BD:
					reset_bit(P1M1, pin);
					reset_bit(P1M2, pin);
					break;
				case GPIO_MODE_PP:
					reset_bit(P1M1, pin);
					set_bit(P1M2, pin);
					break;
				case GPIO_MODE_HI:
					set_bit(P1M1, pin);
					reset_bit(P1M2, pin);
					break;
				case GPIO_MODE_OD:
					set_bit(P1M1, pin);
					set_bit(P1M2, pin);
					break;
				default:
					break;
			}
			break;

//		case 2:
//			switch(mode){
//				case GPIO_MODE_BD:
//					reset_bit(P2M1, pin);
//					reset_bit(P2M2, pin);
//					break;
//				case GPIO_MODE_PP:
//					reset_bit(P2M1, pin);
//					set_bit(P2M2, pin);
//					break;
//				case GPIO_MODE_HI:
//					set_bit(P2M1, pin);
//					reset_bit(P2M2, pin);
//					break;
//				case GPIO_MODE_OD:
//					set_bit(P2M1, pin);
//					set_bit(P2M2, pin);
//					break;
//				default:
//					break;
//			}
//			break;
		
		case 3:
			switch(mode){
				case GPIO_MODE_BD:
					reset_bit(P3M1, pin);
					reset_bit(P3M2, pin);
					break;
				case GPIO_MODE_PP:
					reset_bit(P3M1, pin);
					set_bit(P3M2, pin);
					break;
				case GPIO_MODE_HI:
					set_bit(P3M1, pin);
					reset_bit(P3M2, pin);
					break;
				case GPIO_MODE_OD:
					set_bit(P3M1, pin);
					set_bit(P3M2, pin);
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}
}
#endif
#if (GPIO_INT_ENABLE == 1)
//H, R = 1; L, F = 0;
//level = 1; edge = 0;
void gpio_int_config(uint8_t port, uint8_t pin, uint8_t level_edge, uint8_t H_L_R_F)
{
	switch(port){
	case 0:
		Enable_INT_Port0;
		break;
	case 1:
		Enable_INT_Port1;
		break;
	case 2:
		Enable_INT_Port2;
		break;
	case 3:
		Enable_INT_Port3;
		break;
	default:
		break;
	}
	
	if(level_edge == 0){
		if(H_L_R_F == 0){
			switch(pin){
			case 0:
				Enable_BIT0_FallEdge_Trig;
				break;
			case 1:
				Enable_BIT1_FallEdge_Trig;
				break;
			case 2:
				Enable_BIT2_FallEdge_Trig;
				break;
			case 3:
				Enable_BIT3_FallEdge_Trig;
				break;
			case 4:
				Enable_BIT4_FallEdge_Trig;
				break;
			case 5:
				Enable_BIT5_FallEdge_Trig;
				break;
			case 6:
				Enable_BIT6_FallEdge_Trig;
				break;
			case 7:
				Enable_BIT7_FallEdge_Trig;
				break;
			default:
				break;
			}	
		}
		else{
			switch(pin){
			case 0:
				Enable_BIT0_RasingEdge_Trig;
				break;
			case 1:
				Enable_BIT1_RasingEdge_Trig;
				break;
			case 2:
				Enable_BIT2_RasingEdge_Trig;
				break;
			case 3:
				Enable_BIT3_RasingEdge_Trig;
				break;
			case 4:
				Enable_BIT4_RasingEdge_Trig;
				break;
			case 5:
				Enable_BIT5_RasingEdge_Trig;
				break;
			case 6:
				Enable_BIT6_RasingEdge_Trig;
				break;
			case 7:
				Enable_BIT7_RasingEdge_Trig;
				break;
			default:
				break;
			}	
		}
	}	
	
	if(level_edge == 1){
		if(H_L_R_F == 0){
			switch(pin){
			case 0:
				Enable_BIT0_LowLevel_Trig;
				break;
			case 1:
				Enable_BIT1_LowLevel_Trig;
				break;
			case 2:
				Enable_BIT2_LowLevel_Trig;
				break;
			case 3:
				Enable_BIT3_LowLevel_Trig;
				break;
			case 4:
				Enable_BIT4_LowLevel_Trig;
				break;
			case 5:
				Enable_BIT5_LowLevel_Trig;
				break;
			case 6:
				Enable_BIT6_LowLevel_Trig;
				break;
			case 7:
				Enable_BIT7_LowLevel_Trig;
				break;
			default:
				break;
			}				
		}
		else{
			switch(pin){
			case 0:
				Enable_BIT0_HighLevel_Trig;
				break;
			case 1:
				Enable_BIT1_HighLevel_Trig;
				break;
			case 2:
				Enable_BIT2_HighLevel_Trig;
				break;
			case 3:
				Enable_BIT3_HighLevel_Trig;
				break;
			case 4:
				Enable_BIT4_HighLevel_Trig;
				break;
			case 5:
				Enable_BIT5_HighLevel_Trig;
				break;
			case 6:
				Enable_BIT6_HighLevel_Trig;
				break;
			case 7:
				Enable_BIT7_HighLevel_Trig;
				break;
			default:
				break;
			}	
		}
	}
}

void gpio_int_config_clean(void)
{
	PICON=0x00;PINEN=0x00;PIPEN=0x00;
}
#endif
#if (PWM_ENABLE == 1)
//#define PWN_P 0X03e7 //0X03e7 -> 2k	//0X0063 20k //0X02D6 -> 2.75K // 0X01f3 -> 4k
/**********************************************************************
 PWM frequency = Fpwm/((PWMPH,PWMPL) + 1) <Fpwm = Fsys/PWM_CLOCK_DIV>
  = (16MHz/8)/(0x7CF + 1)
  = 1KHz (1ms)
***********************************************************************/
void pwm_init(uint16_t frequency_KHz)
{
	if(frequency_KHz <= 2000){
		frequency_KHz = (2000/frequency_KHz) - 1;
		
		PWM_IMDEPENDENT_MODE;
		PWM_CLOCK_DIV_8;	//2MHz
		
		PWMPH = (uint8_t)(frequency_KHz>>8);
		PWMPL = (uint8_t)(frequency_KHz);
		
		set_LOAD;
	}
}

void pwm_set(uint8_t channel, uint8_t duty_cycle_in_100)
{
	uint32_t temp = 0;
	
	if(duty_cycle_in_100 > 100){
		return;
	}
	
	temp = PWMPH;
	temp <<= 8;
	temp |= PWMPL;
	temp = (temp*duty_cycle_in_100)/100;
	
	set_SFRPAGE;	
	switch(channel){
		case 0:
			PWM0H = (uint8_t)(temp>>8);
			PWM0L = (uint8_t)(temp);
			break;
		case 1:
			PWM1H = (uint8_t)(temp>>8);
			PWM1L = (uint8_t)(temp);
			break;
		case 2:
			PWM2H = (uint8_t)(temp>>8);
			PWM2L = (uint8_t)(temp);
			break;
		case 3:
			PWM3H = (uint8_t)(temp>>8);
			PWM3L = (uint8_t)(temp);
			break;	
		case 4:
			PWM4H = (uint8_t)(temp>>8);
			PWM4L = (uint8_t)(temp);
			break;	
		case 5:
			PWM5H = (uint8_t)(temp>>8);
			PWM5L = (uint8_t)(temp);
			break;	
	
	}
	clr_SFRPAGE;	
	
	set_LOAD;
}
/************************************************************
 e.g.
	gpio_mode_config(0, 3, GPIO_MODE_PP);	//set the gpio mode as output
	pwm_init(38);							//pwm frequency 38KHz
	pwm_set(5, 10);							//pwm channel 5, duty_cycle 10% 
	pwm_start();							//pwm running
	
	while(1){
		PWM5_P03_OUTPUT_ENABLE;				//pwm channel 5 output in P03 enable
		delay_1ms(100);
		PWM5_P03_OUTPUT_DISABLE;			//pwm channel 5 output in P03 disable
		P30 = 0;							//when pwm output pin disalbed, the pin always keep output a high level
											//so we need to reset the pin output level to low
		delay_1ms(100);
	}

************************************************************/

/************************************************************
 * //WRONG!!
void pwm_pin_set(uint8_t channel, uint8_t pin_num, uint8_t enable_pin)	//don't forget to set the gpio mode as output
{
	bit BIT_TMP;

//	P00 -> channel 0; 
//	P01 -> channel 1;
//	P02 -> channel 2; 
//	P03 -> channel 3;	
//	P04 -> channel 4; 
//	P05 -> channel 5;
//	
//	P11 -> channel 1;
//	P12 -> channel 2; 
//	P13 -> channel 3;	
//	P15 -> channel 5;	

	if(channel != pin_num%10){
		return;
	}
	if((pin_num > 15)||
	((pin_num < 11)&&(pin_num > 5))){
		return;
	}
	
	if(pin_num <= 5){
		if(enable_pin){
			PIOCON0 |= 0x01<<channel;
		}
		else{
			PIOCON0 &= ~(0x01<<channel);
		}
	}
	else if((pin_num >= 11)&&(pin_num <= 15)){
		BIT_TMP=EA;EA=0;TA=0xAA;TA=0x55;SFRS|=0x01;
		if(enable_pin){
			PIOCON1 |= 0x01<<channel;
		}
		else{
			PIOCON1 &= ~(0x01<<channel);
		}
		TA=0xAA;TA=0x55;SFRS&=0xFE;EA=BIT_TMP;
	}
}
************************************************************/
#endif
/*
void tim3_init_10ms(void)
{
	//111 1/128 16Mhz/128 -> 0.125Mhz
	set_T3PS2;
	set_T3PS1;
	set_T3PS0;	
	
	//0.125Mhz -> target time 1=8us ... 125=1ms ...
    RH3 = (65536-1250)/256;		//RELOAD_VALUE_H; 
	RL3 = (65536-1250)%256;		//RELOAD_VALUE_L;    
	
	set_ET3;                                    //enable Timer3 interrupt
//    set_EA;                                     //enable interrupts
//	set_TR3;                                    //Timer3 run
}

void tim3_set_10ms(uint16_t time)
{
	time *= 1250;
	
	//1/8 -> 0.125Mhz -> target time 1=8us ... 125=1ms ...
    RH3 = (65536-time)/256;		//RELOAD_VALUE_H; 
	RL3 = (65536-time)%256;		//RELOAD_VALUE_L;    
}
*/
/*
void timer0_init_20us(void)
{
	TIMER0_MODE2_ENABLE;
    clr_T0M;	//clock source Fsys/12 -> 16Mhz/12 -> 4/3Mhz
	
    TH0 = (256-27);            
    TL0 = (256-27);    
    
    set_ET0;                                    //enable Timer0 interrupt
}
*/

void timer0_init_40us(void)
{
	TIMER0_MODE2_ENABLE;
    clr_T0M;	//clock source Fsys/12 -> 16Mhz/12 -> 4/3Mhz	1tick = 3/4us
	
	//53 * 3/4 = 39.75us
	TH0 = (256-53);
	TL0 = (256-53);

    set_ET0;                                    //enable Timer0 interrupt
}

#if (ADC_ENABLE == 1)
uint16_t bandgap_volt_read(void)
{
    uint8_t BandgapHigh, BandgapLow;
	uint16_t Bandgap_Value;
	unsigned long int  Bandgap_Voltage;
//    set_IAPEN; 
//    IAPAL = 0x0C;
//    IAPAH = 0x00;
//    IAPCN = 0x04;
//    set_IAPGO; // Trig set IAPGO
//    BandgapHigh = IAPFD;
//    IAPAL = 0x0d;
//    IAPAH = 0x00;
//    IAPCN = 0x04;
//    set_IAPGO; // Trig set IAPGO
//    BandgapLow = IAPFD;
//    clr_IAPEN;
	BandgapHigh = _IAP_CMD(0x000c, IAP_CMD_READ_UID, 0);
	BandgapLow = _IAP_CMD(0x000d, IAP_CMD_READ_UID, 0);
    BandgapLow = BandgapLow & 0x0F;
	Bandgap_Value = (BandgapHigh<<4)+BandgapLow; 
	Bandgap_Voltage = Bandgap_Value;
	Bandgap_Voltage = Bandgap_Voltage*3072;
	Bandgap_Voltage = Bandgap_Voltage>>12;//Bandgap_Voltage/4096
//	Bandgap_Voltage = 3072/(0x1000/Bandgap_Value);
	return (uint16_t)Bandgap_Voltage;
}

//when the adc was reseted, first three adc datas should be ignore
uint16_t adc_read(uint8_t channel)
{
	uint16_t targetAD;

	switch(channel){
		case 0:
			Enable_ADC_AIN0;
			break;
		case 1:
			Enable_ADC_AIN1;
			break;
		case 2:
			Enable_ADC_AIN2;
			break;
		case 3:
			Enable_ADC_AIN3;
			break;
		case 4:
			Enable_ADC_AIN4;
			break;
		case 5:
			Enable_ADC_AIN5;
			break;
		case 6:
			Enable_ADC_AIN6;
			break;
		case 7:
			Enable_ADC_AIN7;
			break;
		default:
			Enable_ADC_BandGap;
			break;
	}
	clr_ADCF;
	set_ADCS;																	// Each time ADC start trig signal
	while(ADCF == 0);
	targetAD =  ADCRH;
	targetAD <<=  8;
	targetAD |=  ADCRL<<4;	
	targetAD >>= 4;

	return targetAD;
}
/****
#define BANDGAP_VOLT	122
//TARGET_v = TARGET_ad * BANDGAP_v / BANDGAP_ad
uint8_t adc_get_volt(uint8_t channel)
{
	uint16_t BandGapAD;
	uint32_t targetAD;
	
	Enable_ADC_BandGap;
	clr_ADCF;
	set_ADCS;																	// Each time ADC start trig signal
	while(ADCF == 0);
	BandGapAD =  ADCRH;
	BandGapAD <<=  8;
	BandGapAD |=  ADCRL<<4;	
	BandGapAD >>= 4;
	
	adc_disable();		//????
	
	switch(channel){
		case 0:
			Enable_ADC_AIN0;
			break;
		case 1:
			Enable_ADC_AIN1;
			break;
		case 2:
			Enable_ADC_AIN2;
			break;
		case 3:
			Enable_ADC_AIN3;
			break;
		case 4:
			Enable_ADC_AIN4;
			break;
		case 5:
			Enable_ADC_AIN5;
			break;
		case 6:
			Enable_ADC_AIN6;
			break;
		case 7:
			Enable_ADC_AIN7;
			break;
		default:
			Enable_ADC_BandGap;
			break;
	}
	clr_ADCF;
	set_ADCS;																	// Each time ADC start trig signal
	while(ADCF == 0);
	targetAD =  ADCRH;
	targetAD <<=  8;
	targetAD |=  ADCRL<<4;	
	targetAD >>= 4;
	
	adc_disable();
	
	targetAD = targetAD*BANDGAP_VOLT;
	targetAD = targetAD/BandGapAD;
	
	return targetAD;
}
****/
#endif
#if (INTERNAL_FLASH_ENABLE == 1)
/*************************************
INTERNAL FLASH: LDROM, APROM, CONFIGROM

LDROM: 0x0000->0x0fff
APROM: 0x0000->0x47ff
The logic boundary addresses of APROM and LDROM are defined
by CONFIG1[2:0].

FLASH -> PAGE -> 128 BYTE
/*************************************/
uint16_t flash_byte_addr_to_page_addr(uint16_t byte_addr)
{
	byte_addr &= 0xff80;	// byte_addr = byte_addr/128;
	return byte_addr;
}

uint8_t flash_byte_addr_to_byte_offset_in_page(uint16_t byte_addr)
{
	byte_addr &= 0x000f;	//byte_addr &= ~0xff80; byte_addr = byte_addr%128;
	return byte_addr;
}

void flash_erase_page_aprom(uint16_t page_addr)	//5ms, auto blocked
{
	set_APUEN;
	_IAP_CMD(page_addr, IAP_CMD_APROM_ERASE_PAGE, 0xff);
	clr_APUEN;
}

uint8_t flash_read_byte(uint16_t byte_addr)
{
	uint8_t rdata;
	rdata = *((uint16_t code *)byte_addr)>>8;
	return rdata;
}

void flash_write_byte_aprom(uint16_t byte_addr, uint8_t wdata)
{
	set_APUEN;
	_IAP_CMD(byte_addr, IAP_CMD_APROM_PROGRAM_BYTE, wdata);
	clr_APUEN;
}
/*
void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
{
	UINT8 looptmp=0,u8_addrl_r;
	unsigned char code *cd_longaddr;
	unsigned char xdata *xd_tmp;
	
//Check page start address
	u8_addrl_r = u16_addr;
	if (u8_addrl_r<0x80)
	{
		u8_addrl_r = 0;
	}
	else 
	{
		u8_addrl_r = 0x80;
	}
//Save APROM data to XRAM
	xd_tmp = 0x80;
	cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;	
	while (xd_tmp !=0x100)
	{
		*xd_tmp = *cd_longaddr;
		looptmp++;
		xd_tmp++;
		cd_longaddr++;
	}
// Modify customer data in XRAM
	u8_addrl_r = u16_addr;
	if (u8_addrl_r<0x80)
	{
		xd_tmp = u8_addrl_r+0x80;
	}
	else
	{
		xd_tmp = u8_addrl_r+0;
	}
	*xd_tmp = u8_data;
//Erase APROM DATAFLASH page
	IAPAL = u16_addr;
	IAPAH = u16_addr>>8;
	IAPFD = 0xFF;
	set_IAPEN; 
	set_APUEN;
    IAPCN = 0x22; 		
	set_IAPGO; 
//Save changed RAM data to APROM DATAFLASH
	u8_addrl_r = u16_addr;
	if (u8_addrl_r<0x80)
	{
		u8_addrl_r =0;
	}
	else
	{
		u8_addrl_r = 0x80;
	}
	xd_tmp = 0x80;
	IAPAL = u8_addrl_r;
    IAPAH = u16_addr>>8;
	set_IAPEN; 
	set_APUEN;
	IAPCN = 0x21;
	while (xd_tmp !=0xFF)
	{
		IAPFD = *xd_tmp;
		set_IAPGO;
		IAPAL++;
		xd_tmp++;
	}
	clr_APUEN;
	clr_IAPEN;
}	

uint8_t read_APROM_BYTE(uint16_t code *u16_addr)
{
	uint8_t rdata;
	rdata = *u16_addr>>8;
	return rdata;
}
*/
#endif